home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
- //----------------------------------------------------------------------------
- #include <owl/pch.h>
- #include <owl/defs.h>
- #include <time.h>
- #include <stdio.h>
- #include <string.h>
- #include "wcdefs.h"
- #include "wchess.h"
- #include "externs.h"
-
- //
- // Global Variables
- //
- MOVETYPE ZeroMove = { 8, 8, 0, empty, empty };
- CLOCKTYPE ChessTime[2];
- MOVETYPE KeyMove;
- BOOL Running;
- COLORTYPE RunColor;
- BOOL Analysis, Opan;
- double WantedTime;
- BOOL GameOver = FALSE;
- char EndGameMessage[80];
-
- extern double AverageTime;
-
-
- void EndMessage(char *);
-
- //
- // Initialize the chess clocks
- //
- void
- InitChessTime()
- {
- InitTime(&ChessTime[white]);
- InitTime(&ChessTime[black]);
- }
-
- void
- StopChessTime()
- {
- if (Running) {
- StopTime(&ChessTime[RunColor]);
- KillTimer(hWndMain, TIMEID);
- Running = FALSE;
- }
- }
-
- //
- // Stop the running chess clock and start the clock for color
- //
- void
- StartChessTime(COLORTYPE color)
- {
- RunColor = color;
- Running = TRUE;
- StartTime(&ChessTime[RunColor]);
- SetTimer(hWndMain, TIMEID, 1000, 0);
- }
-
- //
- // reset MovTab
- //
- void
- ResetMoves()
- {
- Depth = -1;
- MovTab[-1] = ZeroMove;
- }
-
- //
- // Clear HintLine
- //
- void
- ClearHint()
- {
- HintLine[0] = ZeroMove;
- HintEvalu = 0;
- }
-
- void
- InitNode(NODEVAL* nodes)
- {
- nodes->nodebase = 0;
- nodes->nodeoffset = 0;
- }
-
- //
- // Test if the move is legal for Programcolor == player in the
- // given position
- //
- BOOL
- IllegalMove(MOVETYPE* move)
- {
- Perform(move, 0);
- BOOL illegal = Attacks(Opponent, PieceTab[Player][0].isquare);
- Perform(move, 1);
- return illegal;
- }
-
- //
- // Make move for programcolor = player and updates variables
- //
- void
- MakeMove(MOVETYPE* move)
- {
- Depth++;
- MoveNo++;
- Perform(move, 0);
- ProgramColor = Opponent;
- Opponent = Player;
- Player = ProgramColor;
- }
-
- //
- // Prints comment to the game (check, mate, draw, resign)
- //
- void
- PrintComment()
- {
- short check, possiblemove, checkmate;
- int nummoves;
-
- Message("");
- checkmate = 0;
- Depth++;
- possiblemove = 0;
- InitMovGen();
- do {
- MovGen();
- if (Next.movpiece != empty)
- if (!IllegalMove(&Next))
- possiblemove = 1;
- } while (Next.movpiece != empty && !possiblemove);
-
- Depth--;
- check = Attacks(Opponent, PieceTab[Player][0].isquare); // calculate check
- // No possible move means checkmate or stalemate
- if (!possiblemove) {
- if (check) {
- checkmate = 1;
- EndMessage("CheckMate");
- } else
- EndMessage("Stalemate!");
-
- } else
- if (HintEvalu >= MATEVALUE - DEPTHFACTOR * 16) {
- nummoves = (MATEVALUE - HintEvalu + 0x40) / (DEPTHFACTOR * 2);
- sprintf(buf, "Mate in %d Move%s", nummoves, (nummoves > 1) ? "s!" : "!");
- Message(buf);
- }
- if (check && !checkmate)
- Message("Check!");
- else { // test 50 move rule and repetition of moves
- if (FiftyMoveCnt() >= 100) {
- EndMessage("50 Move rule");
- } else
- if (Repetition(0) >= 3) {
- EndMessage("3 fold Repetition");
- } else // Resign if the position is hopeless
- if (-25500 < HintEvalu && HintEvalu < -0x880) {
- switch (Opponent) {
- case white:
- EndMessage(" White resigns");
- break;
- case black:
- EndMessage(" Black resigns");
- }
- }
- }
- }
-
- void
- EnterMove(MOVETYPE* move)
- {
- StopChessTime();
- PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
- MakeMove(move);
- UpdateBoard();
- PrintComment();
- StartChessTime(ProgramColor);
- }
-
- void
- RemoveMove(MOVETYPE* move)
- {
- StopChessTime();
- PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
- TakeBackMove(move);
- UpdateBoard();
- PrintComment();
- StartChessTime(ProgramColor);
- }
-
- //
- // perform the move entered by the user
- //
- void
- EnterKeyMove()
- {
- MovTab[Depth+1] = KeyMove;
- PlayerMove = KeyMove;
- ClearHint();
- DragEnd(TRUE);
- EnterMove(&MovTab[Depth+1]);
- }
-
- //
- // move movtab to depth = -1
- //
- void
- AdjustMoves()
- {
- for (int i = Depth; i >= BACK; i--)
- MovTab[i-(Depth+1)] = MovTab[i];
- Depth = -1;
- }
-
- //
- // Move movtab one move BACK
- //
- void
- StoreMoves()
- {
- Depth--;
- for (int i = BACK; i <= Depth; i++)
- MovTab[i] = MovTab[i+1];
- MovTab[BACK] = ZeroMove;
- }
-
- //
- // Check to see if the input move is legal
- //
- BOOL
- MoveCheck(SQUARETYPE startsq, SQUARETYPE endsq)
- {
- Depth++;
- KeyMove = ZeroMove;
- InitMovGen();
- do {
- MovGen();
- if (Next.new1 == endsq && Next.old == startsq) {
- KeyMove = Next;
- break;
- }
- } while (Next.movpiece != empty);
-
- if (KeyMove.movpiece == empty) {
- Warning("Impossible move");
- Depth--;
- return FALSE;
- }
- if (IllegalMove(&KeyMove)) {
- Warning("Illegal move. Check!");
- Depth--;
- return FALSE;
- }
- Depth--;
- if (!ComputerThinking) {
- AdjustMoves();
- EnterKeyMove();
- StoreMoves();
- }
- return TRUE;
- }
-
- //
- // calculate the WANTED response time
- //
- void
- StartAnalysis()
- {
- int timecontrol;
- extern HWND hWndMain;
- extern HCURSOR hWaitCursor;
-
- Analysis = 1;
- Opan = 0;
- SetClassWindowCursor(hWndMain, hWaitCursor);
-
- switch (Level) {
- case easygame:
- case normal:
- // Divides the Time left till nest time control between moves left.
- // There is a margin of 4 moves to make sure that the program does
- // not lose on time
- timecontrol = (((MoveNo >> 1) + 20) / 20) * 20;
- if (timecontrol <= 40)
- timecontrol = 40;
- WantedTime = (AverageTime * timecontrol - ChessTime[ProgramColor].totaltime) /
- (timecontrol + 4 - (MoveNo >> 1));
-
- // In the begining of the game the program thinks
- // around twice as long, since the early middle
- // game is normally the most crucial part of
- // a game
- if ((MoveNo >> 1) <= 40)
- WantedTime = 5.0 + (WantedTime - 5.0) * ((80 - (MoveNo >> 1)) / 40);
- break;
-
- case fullgametime:
- // Assumes that the game will last for around 40 moves and
- // divides the time left accordingly
- WantedTime = (AverageTime * 60.0 - ChessTime[ProgramColor].totaltime) / 44;
-
- // In the begining of the game the program thinks around twice as long,
- // since the early middle game is normally the most crucial part of a
- // game
- if ((MoveNo >> 1) <= 40)
- WantedTime = 5.0 + (WantedTime - 5.0) * ((80 - (MoveNo >> 1)) /40);
- break;
-
- case matching:
- // Spend as much time as the Opponent does
- if (MoveNo >= 2)
- WantedTime = ChessTime[Opponent].totaltime / (MoveNo >> 1);
- else
- WantedTime = 5.0;
- WantedTime += (ChessTime[Opponent].totaltime -
- ChessTime[ProgramColor].totaltime) * 0.25;
-
- //break; //wasn't here???
-
- default:
- WantedTime = 1000000.0;
- }
- }
-
- //
- // take BACK move and update variables
- //
- void
- TakeBackMove(MOVETYPE* move)
- {
- ProgramColor = Opponent;
- Opponent = Player;
- Player = ProgramColor;
- Perform(move, 1);
- MoveNo--;
- Depth--;
- }
-
- void
- IncNode(NODEVAL *nodes)
- {
- if (nodes->nodeoffset >= MAXINT) {
- nodes->nodebase++;
- nodes->nodeoffset = 0;
-
- } else
- nodes->nodeoffset++;
- }
-
-
- void
- Wait(int tenths)
- {
- clock_t NumTicksToWait;
-
- // two ticks == approx. 1/10 second, since 18.2 clocks is approx a
- // second
- NumTicksToWait = tenths*2 + clock();
- while (NumTicksToWait > clock())
- ;
- }
-
- //
- // Flash a move once on the screen
- //
- void
- FlashMove(MOVETYPE* move)
- {
- MakeMove(move);
- UpdateBoard();
- Wait(4);
- TakeBackMove(move);
- UpdateBoard();
- Wait(4);
- }
-
- void
- DoSlideMove(MOVETYPE& move)
- {
- SQUARETYPE castsquare, cornersquare;
- SlidePiece(move.new1, move.old);
- if (move.spe) {
- if (move.movpiece == king) {
- GenCastSquare(move.new1, &castsquare, &cornersquare);
- SlidePiece(castsquare, cornersquare);
- }
- }
- }
-
- void
- EndMessage(char* message)
- {
- strcpy(EndGameMessage, message);
- GameOver = TRUE;
- }
-
- void
- ShowHint()
- {
- DEPTHTYPE dep = 0;
- *buf = 0;
- Message(buf);
- while (HintLine[dep].movpiece != empty) {
- strcat(buf, MoveStr(&HintLine[dep]));
- strcat(buf, " ");
- Message(buf);
- MakeMove(&HintLine[dep]);
- UpdateBoard();
- Wait(6);
- dep++;
- }
- while (dep > 0) {
- dep--;
- TakeBackMove(&HintLine[dep]);
- }
- UpdateBoard();
- }
-